﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Xml;
using System.IO;

namespace CMS
{
    /// <summary>
    /// Summary description for Service1
    /// </summary>
    [WebService(Namespace = "http://proxy.dom/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    [System.Web.Script.Services.ScriptService]
    public class service : System.Web.Services.WebService
    {
        
        /*
         * Access rights to CMS
         */
        public class accessSettings
        {
            public string adminGroup;      //name of a LDAP administrators group
            public string usersGroup;      //name of LDAP users group
            
            public string authType;        //database or LDAP

            //
            public string[] serviceAdmins; //Service administrators

            //CMS roles
            public string[] adviceBoard;   //members of AB
            public string[] changeManagers;//CM
            public string[] changeImplementers;
            public string[] equipmentManagers;
            public accessSettings() {                
            }
        }
        /*
         * Database Settings
         */
        public struct dbSettings
        {
            public string server;
            public string instance;
            public string dbname;
            public string login;
            public string pwd;
        }
        /*
         * CMS settings
         */
        public struct cmsSettings
        {
            public int MaxAllowedABMembers;
            public int MaxAllowedOpenCRsPerPerson;
            public int showCRsByPage;
            public int maxAllowedLoggedInUsers;
            public int idleTimeAllowed;            
        };

        
        //location of settings realtive file
        private static string ProjectSettingsPath = @"~/App_data/settings.xml";
        public static string RealPath;          //absolute path of settings
        static XmlNode setts;                   //contains DOM structure of settings
        static CMS_DB cmdb;
        static Security check;

        //settings init
        static public accessSettings accessRights = new accessSettings();
        static public dbSettings dbAccess = new dbSettings();
        static public cmsSettings cmsSetts = new cmsSettings();
        /* 
         * Keeps  Track of users, who is logged in
         */
        public static List<AuthentificatedUser> authentificatedUsers = new List<AuthentificatedUser>(Convert.ToInt32(cmsSetts.maxAllowedLoggedInUsers));





        //===================================================================
        public service(){
            RealPath = Server.MapPath(ProjectSettingsPath); //locate settings

            //Initialise Users

            readSettings();

            initializeDatabase();

            if (accessRights.authType == "LDAP")
            {
                initializeLDAP();
            }

            check = new Security();
        }

        #region LDAP init
        private void initializeLDAP()
        {
            throw new NotImplementedException();
        }
        #endregion

        private void initializeDatabase()
        {
            cmdb = new CMS_DB();

            
            //ex.exs = connectionString;
        }

        /*
         * Reads settings from XML
         */
        #region settings initialisation
        private void readSettings()
        {
            /* loading settings file */
            XmlDocument settings = new XmlDocument();
            settings.Load(CMS.service.RealPath);
            setts = settings.DocumentElement;

            /* CMS settings */
            cmsSetts.MaxAllowedABMembers = Convert.ToInt32(setts.SelectSingleNode("/cms/MaxAllowedABmembers").ChildNodes[0].Value);
            cmsSetts.MaxAllowedOpenCRsPerPerson = Convert.ToInt32(setts.SelectSingleNode("/cms/MaxAllowedOpenedCRsPerPerson").ChildNodes[0].Value);
            cmsSetts.showCRsByPage = Convert.ToInt32(setts.SelectSingleNode("/cms/CRsPerPage").ChildNodes[0].Value);
            cmsSetts.maxAllowedLoggedInUsers = Convert.ToInt32(setts.SelectSingleNode("/cms/maxAllowedLoggedInUsers").ChildNodes[0].Value);
            cmsSetts.idleTimeAllowed = Convert.ToInt32(setts.SelectSingleNode("/cms/idleTimeAllowed").ChildNodes[0].Value);

            /* Reding Access rights related settings */
            accessRights.adminGroup = setts.SelectSingleNode("/cms/admin_group").ChildNodes[0].Value;
            accessRights.usersGroup = setts.SelectSingleNode("/cms/users_group").ChildNodes[0].Value;

            accessRights.adviceBoard = new string[cmsSetts.MaxAllowedABMembers];
            
            //***AB
            XmlNodeList AB = setts.SelectNodes("/cms/advice_board/member");
            int i=0;
            foreach (XmlNode adbomem in AB)
            {                
                accessRights.adviceBoard[i] = adbomem.FirstChild.InnerText;
                i++;
            }
            i = 0;
            //***ServiceAdministrators
            XmlNodeList admins = setts.SelectNodes("/cms/administrators/admin");
            accessRights.serviceAdmins = new string[5];
            foreach (XmlNode cmsadm in admins)
            {
                accessRights.serviceAdmins[i] = cmsadm.FirstChild.InnerText;
                i++;
            }
            i = 0;
            //***CM
            XmlNodeList CM = setts.SelectNodes("/cms/change_managers/cm");
            accessRights.changeManagers = new string[5];
            foreach (XmlNode cm in CM)
            {
                accessRights.changeManagers[i] = cm.FirstChild.InnerText;
                i++;
            }
            //***EM
            i = 0;
            XmlNodeList EM = setts.SelectNodes("/cms/equipment_managers/em");
            accessRights.equipmentManagers = new string[5];
            foreach (XmlNode em in EM) {
                accessRights.equipmentManagers[i] = em.FirstChild.InnerText;
                i++;
            }
            //***CIM
            i = 0;
            XmlNodeList CIM = setts.SelectNodes("/cms/change_implementers/cim");
            accessRights.changeImplementers = new string[5];
            foreach (XmlNode cim in CIM) {
                accessRights.changeImplementers[i] = cim.FirstChild.InnerText;
                i++;
            }

            accessRights.authType = setts.SelectSingleNode("/cms/auth_type").ChildNodes[0].Value;

            /*reading Database related settings */
            dbAccess.server = setts.SelectSingleNode("/cms/server_url").ChildNodes[0].InnerText;
            dbAccess.instance = setts.SelectSingleNode("/cms/instance").ChildNodes[0].Value;
            dbAccess.dbname = setts.SelectSingleNode("/cms/database").ChildNodes[0].Value;
            dbAccess.login = setts.SelectSingleNode("/cms/login").ChildNodes[0].Value;
            dbAccess.pwd = setts.SelectSingleNode("/cms/password").ChildNodes[0].Value;
        }
        #endregion


        //====================================================================
        //          WEB         METHODS         BOOO!
        //====================================================================
        
        /*
         * Logges UserIn
         * Password should be MD5 -encrypted!!!
         * returns Statuses:
         * 1 - login success
         * 2 - username and password do not match
         * 3 - User is already logged in
         */
        [WebMethod]
        public loginStatus login(string username, string password, string hostname)
        {
            if (service.accessRights.authType == "DB")
            {
                if (!CMS_input_validation.isUsername(username))
                    return new loginStatus(2, username);
                if (!CMS_input_validation.isPassword(password))
                    return new loginStatus(10, username);
                if (!CMS_input_validation.isHostname(hostname))
                    return new loginStatus(11, username);

                //check if user exists in database
                //check result of username and password match in database
                if (cmdb.isUserValidExists(username,password) == false) {
                    return new loginStatus(2); //false
                } else {
                    AuthentificatedUser pretender = new CMS.AuthentificatedUser();
                    pretender.UserName = username;

                    //check, if user is already logged in and has the same coockie and ip is the same
                    if (Security.isLoggedIn(pretender)) {
                        //TODO check if it is really the same user by ip and coockie                        
                        return new loginStatus(3, username);//user logged in.
                    }

                    //pretender.userID = cmdb.getUserIdByUsername(username);

                    //check, if user is administrator or casual user
                    pretender.serviceGR = Security.detectServiceGroup(pretender.username);

                    //detect user's Change management role
                    pretender.cmsRoles = Security.detectCMSGroup(pretender.username);
                    
                    //Get hostname
                    pretender.HostName = hostname;
                    //generate coockie
                    
                    //register user session
                    authentificatedUsers.Add(pretender);

                    //send coockie
                    loginStatus answer = new loginStatus(1, pretender);
                    answer.sessionID = pretender.SessionID;
                    //answer.userID = pretender.userID;
                    return answer;
                }
            }
            else if (service.accessRights.authType == "LDAP")
            {                
                return new loginStatus(5 , username);
            }
            else
            {
                return new loginStatus(6 , username);
            }
        }        

        
        #region logout 

        /*
         * loggs logged in user out.
         * Has 3 possible responses:
         * 7   Success! User logged out
         * 8   Can not log out user - not enough credentials provided
         * 9   User not logged in
         */
        [WebMethod]
        public logoutStatus logout(APIAccessToken token){  
            //check if sent data matches save data about session
            if (!Security.IsSenderValid(token))
                return new logoutStatus(8, token.username);

            //check if correct user tries to log out
            if (Security.isLoggedIn(token.username)) {

                //remove session from memory
                foreach (AuthentificatedUser us in authentificatedUsers) {
                    if (us.UserName == token.username) {
                        authentificatedUsers.Remove(us);
                        break;
                    }
                }
                //return success status
                return new logoutStatus(7, token.username);
            }
            return new logoutStatus(9, token.username);
        }
        #endregion


        //=================================CI===================================
        #region CI

        /*
         * returns true if request was created, false if not
         * ACCESS: any logged in user
         */
        [WebMethod]
        public listOfCRs CreateChangeRequest(APIAccessToken token, string reqText) {
            //add validity check
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            long userid = cmdb.getUserIdByUsername(token.username);

            long result = cmdb.createChangeRequest(userid, reqText);

            CRArray effect = cmdb.getCRByID(result);
            listOfCRs answer = new listOfCRs(15, effect);

            return answer;
        }

        /*
         * shows CR by ID
         * ACCESS: any logged in user.
         * note: for privacy reasons CI can see only their requests, but 
         * CM and AB can see any. 
         **/
        [WebMethod]
        public listOfCRs getCrByID(APIAccessToken token, long crid) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);

            //check access rights!!!

            CRArray result = cmdb.getCRByID(crid);

            return new listOfCRs(15, result);
        }
        /*
         * lists open CR's initiated by requester
         * ACCESS: CI
         */        
        [WebMethod]
        public listOfCRs listOpenCrByCI(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            //check request validity
            
            long userID = cmdb.getUserIdByUsername(token.username);

            CRArray ds = cmdb.getCRsByCI(userID, true);
            
            return new listOfCRs (15, ds);
        }

        /*
         * lists history of CR's, i.e. closed CR's
         * ACCESS: CI
         */
        [WebMethod]
        public listOfCRs listClosedCRByCI(APIAccessToken token) {
            if(!Security.IsSenderValid(token))
                return new listOfCRs(14);

            long ciID = cmdb.getUserIdByUsername(token.username);
            CRArray result = cmdb.getCRsByCI(ciID, false);
            return new listOfCRs(15, result);
        }

        /*
         * if CR is not evaluated by CM, Ci can edit request
         */
        [WebMethod]
        public listOfCRs editOpenCRfromCI(APIAccessToken token, ChangeRequest cr) {
            long affectedCR;
            CRArray result;
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!cr.isEvaluated) {
                affectedCR = cmdb.updateCRfromCI(cr);
                result = cmdb.getCRByID(affectedCR);
                return new listOfCRs(15, result);
            } else {
                return new listOfCRs(19);
            }
        }

        #endregion 

        //=================================CM===================================
        #region CM

        /*
         * lists CR's managed by requester
         * ACCESS: CM
         */
        [WebMethod(Description="lists CR's managed by requester")]
        public listOfCRs ListManagedCR(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isChangeManager(token.username))
                return new listOfCRs(16);

            long userID = cmdb.getUserIdByUsername(token.username);
            CRArray result = cmdb.getCRsByCM(userID, false, true);

            return new listOfCRs(15, result);
        }
        /*
         * lists CR's without CM assigned
         * ACCESS: CM
         */
        [WebMethod]
        public listOfCRs ListCRsWithoutCM(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isChangeManager(token.username))
                return new listOfCRs(16);
            long cmID = cmdb.getUserIdByUsername(token.username);
            CRArray result = cmdb.getCRsWithoutCM();
            return new listOfCRs(15, result);
        }

        /*
         * assigns CM to all unassigned CR's
         * ACCESS: cm
         */
        [WebMethod]
        public listOfCRs assignCMtoAllCRs(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isChangeManager(token.username))
                return new listOfCRs(16);
            long cmID = cmdb.getUserIdByUsername(token.username);
            if(!cmdb.assignCMtoAllCRs(cmID))
                return new listOfCRs(13);
            else
                return new listOfCRs(15);
        }

        /*
         * assigns CM to chosen CR
         * ACCESS: CM
         */
        [WebMethod]
        public listOfCRs assignCMtoCR(APIAccessToken token, long crID) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isChangeManager(token.username))
                return new listOfCRs(16);
            long cmID = cmdb.getUserIdByUsername(token.username);

            long result = cmdb.assignCMtoCR(cmID, crID);

            CRArray affectedCR = cmdb.getCRByID(result);
            return new listOfCRs(15, affectedCR);
        }

        /*
         * assigns Evaluates CR by CM
         * ASSCESS: CM
         */
        [WebMethod]
        public listOfCRs evaluateCRfromCM(APIAccessToken token, long crID, string initialRequest, string impact, string cost) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isChangeManager(token.username))
                return new listOfCRs(16);
            long cmID = cmdb.getUserIdByUsername(token.username);
            ChangeRequest cr = new ChangeRequest();
            cr.ID = crID;
            cr.cm = (int)cmID;
            cr.request = initialRequest;
            cr.impactEstim = impact;
            cr.costEstim = cost;
            long affectedCr = cmdb.evaluateCRfromCM(cr);
            CRArray update = cmdb.getCRByID(affectedCr);
            return new listOfCRs(15, update);
        }

        /*
         * adds Computer co CR
         * ACCESS: CM
         */
        [WebMethod]
        public listOfComputers addPcAffected(APIAccessToken token, long crid, string pcID) {
            if (!Security.IsSenderValid(token))
                return new listOfComputers(14);
            if (!Security.isChangeManager(token.username))
                return new listOfComputers(16);
            //add completion check
            cmdb.assignComputerAffectedToCR(crid, pcID);
            ComputerArray resultedPC = cmdb.getComputerByID(pcID);
            return new listOfComputers(15, resultedPC);
        }

        /*
         * adds software to be affected by CR
         * ACCESS: CM
         */
        [WebMethod]
        public listOfSoftwares addSoftwareAffected(APIAccessToken token, long crid, long softID) {
            if (!Security.IsSenderValid(token))
                return new listOfSoftwares(14);
            if (!Security.isChangeManager(token.username))
                return new listOfSoftwares(16);
            //add completion check
            cmdb.asignSoftwareAffectedToCR(crid, softID);
            SoftwareArray soft = cmdb.getSoftByID(softID);
            return new listOfSoftwares(15, soft);
        }
        /*
         * adds PT to be affected by CR
         * ACCESS: CM
         */
        [WebMethod]
        public listOfPlainTexts addPTAffected(APIAccessToken token, long crid, long ptID) {
            if (!Security.IsSenderValid(token))
                return new listOfPlainTexts(14);
            if (!Security.isChangeManager(token.username))
                return new listOfPlainTexts(16);
            //add completion check
            cmdb.assignPTAfefectedToCr(crid, ptID);
            PTArray result = cmdb.getPTbyID(ptID);
            return new listOfPlainTexts(15, result);
        }
        /*
         * adds PS to be affected by CR
         * ACCESS: CM
         */
        [WebMethod]
        public listOfPartialStates addPSAffected(APIAccessToken token, long crid, long psID) {
            if (!Security.IsSenderValid(token))
                return new listOfPartialStates(14);
            if (!Security.isChangeManager(token.username))
                return new listOfPartialStates(16);
            //add completion check
            cmdb.assignPSAffectdToCR(crid, psID);
            PSArray result = cmdb.getPSbyID(psID);
            return new listOfPartialStates(15, result);
        }

        #endregion



        //=================================EM===================================
        #region EM
        
        /*
         * Gives List Of Computer IDs
         * ACCESS: CM, EM, cim
         */
        [WebMethod]
        public listOfCompIDs getListOfComputerIDs(APIAccessToken token){
            if (!Security.IsSenderValid(token))
                return new listOfCompIDs(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfCompIDs(16);
            DataSet list = cmdb.getListOfCompIDs();
            return new listOfCompIDs(15, list);
        }
        /*
         * Gives full Computer Data by Computer ID
         * ACCESS: CM, EM, CIM
         */
        [WebMethod]
        public listOfComputers getComputerByID(APIAccessToken token, string compID) {
            if (!Security.IsSenderValid(token))
                return new listOfComputers(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfComputers(16);
            ComputerArray result = cmdb.getComputerByID(compID);
            return new listOfComputers(15, result);
        }
        
        /*
         * Addds New Computer
         * ACCESS:  EM, CIM
         */
        [WebMethod]
        public listOfComputers addNewComputer(APIAccessToken token, Computer pc) {
            if (!Security.IsSenderValid(token))
                return new listOfComputers(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username))
                return new listOfComputers(16);
            string newID = cmdb.addNewComputer(pc);

            if (newID == "-2")
                return new listOfComputers(20);
            if (newID == "-1")
                return new listOfComputers(17);
            ComputerArray result = cmdb.getComputerByID(newID);
            return new listOfComputers(15, result);
        }
        /*
         * returns list of registred enterprise users
         * ACCESS: any logged in user
         */
        [WebMethod(Description="returns list of registred enterprise users ACCESS: any logged in user")]
        public listOfUsers getListOfUsers(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfUsers(14);
            List<string> list = new List<string>();
            list = cmdb.getListOfUsers();
            if (list.Count == 0)
                return new listOfUsers(18);
            else
                return new listOfUsers(15, list);
        }
        /*
         * Adds New User
         * ACCESS: EM
         */
        [WebMethod]
        public listOfUsers addNewUser(APIAccessToken token, string username, string password) {
            if (!Security.IsSenderValid(token))
                return new listOfUsers(14);
            if (!Security.isEquipmentManager(token.username))
                return new listOfUsers(16);
            
            //username should be unique!

            long newUserID = cmdb.addNewEnterpriseUser(username, password);
            if (newUserID == -1)
                return new listOfUsers(21);

            List<string> newUser = new List<string>();
            newUser.Add(token.username);
            return new listOfUsers(15, newUser);
        }
        /*
         * Gives list of full OperatingSystem Data by Computer ID
         * ACCESS: CM, EM, CIM
         */
        [WebMethod]
        public listOfOperatingSystems getOSlistByCompID(APIAccessToken token, string compID) {
            if (!Security.IsSenderValid(token))
                return new listOfOperatingSystems(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfOperatingSystems(16);

            OSArray result = cmdb.getOSByCompID(compID);
            return new listOfOperatingSystems(15, result);
        }
        /*
         * Adds New OS to computer
         * ACCESS: EM, CIM
         */
        [WebMethod]
        public listOfOperatingSystems addNewOperatingSystemToComputer(APIAccessToken token, OperatingSystem os) {
            if (!Security.IsSenderValid(token))
                return new listOfOperatingSystems(14);
            if (!Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfOperatingSystems(16);

            long newosid = cmdb.addNewOS(os);

            if (newosid == -2)
                return new listOfOperatingSystems(20);
            if (newosid == -1)
                return new listOfOperatingSystems(17);

            OSArray result = cmdb.getOSByOsID(newosid);
            return new listOfOperatingSystems(15, result);
        }
        /*
         * Gives all softwares on current OS
         * ACCESS: CM, EM, CIM
         */
        [WebMethod]
        public listOfSoftwares getSoftwareListByOsId(APIAccessToken token, long osID) {
            if (!Security.IsSenderValid(token))
                return new listOfSoftwares(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfSoftwares(16);

            SoftwareArray result = cmdb.getSoftByOSID(osID);
            return new listOfSoftwares(15, result);
        }
        /*
         * add new software to OS
         * ACCESS: EM, CIM
         */
        [WebMethod]
        public listOfSoftwares addNewSoftwareToOS(APIAccessToken token, Software soft) {
            if (!Security.IsSenderValid(token))
                return new listOfSoftwares(14);
            if (!Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfSoftwares(16);

            long newSoftID = cmdb.addNewSoftware(soft);
            if (newSoftID == -2)
                return new listOfSoftwares(20);
            if (newSoftID == -1)
                return new listOfSoftwares(17);

            SoftwareArray result = cmdb.getSoftByID(newSoftID);
            return new listOfSoftwares(15, result);
        }
        /*
         * list PS's corresponding to software
         * ACCESS: CM, EM, CIM
         */
        [WebMethod]
        public listOfPartialStates listPartialStatesBySoftID(APIAccessToken token, long softID) {
            if (!Security.IsSenderValid(token))
                return new listOfPartialStates(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfPartialStates(16);
            PSArray result = cmdb.getPSBySoftID(softID);
            return new listOfPartialStates(15, result);
        }
        /*
         * adds new PS to software
         * ACCESS: EM, CIM
         */
        [WebMethod(Description="adds new PS to software.\n ACCESS: EM, CIM")]
        public listOfPartialStates addNewPartialStateToSoftware(APIAccessToken token, PartialStateConfig ps) {
            if (!Security.IsSenderValid(token))
                return new listOfPartialStates(14);
            if (!Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfPartialStates(16);
            long newPS = cmdb.addNewPS(ps);
            if (newPS == -2)
                return new listOfPartialStates(20);
            if (newPS == -1)
                return new listOfPartialStates(17);
            PSArray result = cmdb.getPSbyID(newPS);
            return new listOfPartialStates(15, result);
        }
        /*
         * list PT's by software
         * ACCESS: CM, EM, CIM
         */
        [WebMethod]
        public listOfPlainTexts listPlainTextsBySoftID(APIAccessToken token, long softID) {
            if (!Security.IsSenderValid(token))
                return new listOfPlainTexts(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfPlainTexts(16);
            PTArray result = cmdb.getPTBySoftID(softID);
            return new listOfPlainTexts(15, result);
        }
        /*
         * adds new PT to software
         * ACCESS: EM, CIM
         */
        [WebMethod]
        public listOfPlainTexts addNewPlainTextToSoftware(APIAccessToken token, PlainTextConfig pt) {
            if (!Security.IsSenderValid(token))
                return new listOfPlainTexts(14);
            if (!Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfPlainTexts(16);

            long newPT = cmdb.addNewPT(pt);
            if (newPT == -2)
                return new listOfPlainTexts(20);
            if (newPT == -1)
                return new listOfPlainTexts(17);

            PTArray result = cmdb.getPTbyID(newPT);
            return new listOfPlainTexts(15, result);
        }
        /*
         * Gets type of software
         * ACCESS: CM, EM, CIM
         */        
        [WebMethod]
        public SoftwareType getSoftTypeByID(APIAccessToken token, long SoftTypeID) {
            if (!Security.IsSenderValid(token))
                return new SoftwareType(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new SoftwareType(16);
            SoftType st = cmdb.getSoftTypeByID(SoftTypeID);
            return new SoftwareType(15, st);
        }
        /*
         * Adds new type of software
         * ACCESS: CM, EM, CIM
         */
        [WebMethod]
        public listOfLicenses getLicenseByID(APIAccessToken token, long LicID) {
            if (!Security.IsSenderValid(token))
                return new listOfLicenses(14);
            if (!Security.isChangeManager(token.username) ||
                !Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfLicenses(16);
            licenseArray result = cmdb.getLicenceByID(LicID);
            return new listOfLicenses(15, result);
        }
        /*
         * Adds new type of software
         * ACCESS: EM, CIM
         */
        [WebMethod]
        public SoftwareType addNewSoftType(APIAccessToken token, SoftType st) {
            if (!Security.IsSenderValid(token))
                return new SoftwareType(14);
            if (!Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new SoftwareType(16);
            long newST = cmdb.addNewSoftwareType(st);
            if (newST == -2)
                return new SoftwareType(20);
            if (newST == -1)
                return new SoftwareType(17);

            SoftType result = cmdb.getSoftTypeByID(newST);
            return new SoftwareType(15, result);
        }

        /*
         * Adds new type of software
         * ACCESS: EM, CIM
         */
        [WebMethod]
        public listOfLicenses addNewLicense(APIAccessToken token, license lic) {
            if (!Security.IsSenderValid(token))
                return new listOfLicenses(14);
            if (!Security.isEquipmentManager(token.username) ||
                !Security.isChangeImplementer(token.username))
                return new listOfLicenses(16);
            long newLicId = cmdb.addNewLicence(lic);
            licenseArray result = cmdb.getLicenceByID(newLicId);
            return new listOfLicenses(15, result);
        }
        
                


        #endregion




        //=================================AB===================================
        #region AB
        
        /*
         * For AB member shows list of CR's to be approved
         * ACCESS: AB
         */
        [WebMethod]
        public listOfCRsWithApproves ListUnapprovedCRsWithApproves(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfCRsWithApproves(14);
            if(!Security.isAdviceBoard(token.username))
                return new listOfCRsWithApproves(16);

            //get list of unapproved CR's
            CRArray inapprovedCRz = cmdb.getCRsUnapprovedByAB(cmdb.getUserIdByUsername(token.username));

            listOfCRsWithApproves CrAppr = new listOfCRsWithApproves();
            //for each inapproved CR get approves
            List<long> cridz = new List<long>();

            while (inapprovedCRz.list.Count > 0) {
                ChangeRequest cr = inapprovedCRz.list.First<ChangeRequest>();
                cridz.Add(cr.ID);
                inapprovedCRz.list.Remove(cr);
            }

            foreach (long crid in cridz) {
                CrAppr.addNew(cmdb.getCRWithApproves(crid));
            }

            return CrAppr;
        }

        /*
         * approves CR or disproves and closes it
         * ACCESS: AB
         */
        [WebMethod]
        public listOfCRsWithApproves ApproveChangeRequest(APIAccessToken token, Approve appr) {
            if (!Security.IsSenderValid(token))
                return new listOfCRsWithApproves(14);
            if (!Security.isAdviceBoard(token.username))
                return new listOfCRsWithApproves(16);
            long result = cmdb.approveCRfromAB(appr);
            CRWithApproves craffected = cmdb.getCRWithApproves(appr.ApprovedCR);
            return new listOfCRsWithApproves(15, craffected);
        }
        /*
         * Closes Implemented CR after AB's revision
         * ACCESS: AB
         */
        [WebMethod]
        public listOfCRs closeUnimplementedCR(APIAccessToken token, long crID) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isAdviceBoard(token.username))
                return new listOfCRs(16);
            long updatedCR = cmdb.setCrClosedAndNotImplemented(crID);
            CRArray newcr = cmdb.getCRByID(updatedCR);
            return new listOfCRs(15, newcr);
        }
        /*
         * lists fully approved CR's to be sheduled
         * ACCESS: AB
         */
        [WebMethod]
        public listOfCRs ListFullyApprovedCRs(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isAdviceBoard(token.username))
                return new listOfCRs(16);
            int amountOfConfiguredAbMembers = accessRights.adviceBoard.Count();

            CRArray result = cmdb.getFullyApprovedCRs(amountOfConfiguredAbMembers);

            return new listOfCRs(15, result);
        }
        /*
         * Shows CR with all items affected.
         * ACCESS: AB
         */
        [WebMethod]
        public listOfCRsWithItems getCRwithWithItemsAffected(APIAccessToken token, long crID) {
            if (!Security.IsSenderValid(token))
                return new listOfCRsWithItems(14);
            if (!Security.isAdviceBoard(token.username))
                return new listOfCRsWithItems(16);
            CRWithDependencies result = cmdb.getCRWithItemsAffected(crID);
            return new listOfCRsWithItems(15, result);
        }
        /*
         * Assigns CIM and sets the implementation date
         * ACCESS: AB
         */
        [WebMethod]
        public listOfCRs assignCIMandShedulrCRimplemetation(APIAccessToken token, ChangeRequest cr) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isAdviceBoard(token.username))
                return new listOfCRs(16);
            long updatedCR = cmdb.sheduleCRAndAssignCIM(cr);
            CRArray newCR = cmdb.getCRByID(updatedCR);
            return new listOfCRs(15, newCR);
        }
        /*
         * Closes Implemented CR after AB's revision
         * ACCESS: AB
         */
        [WebMethod]
        public listOfCRs closeImplementedCR(APIAccessToken token, long crID) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isAdviceBoard(token.username))
                return new listOfCRs(16);
            long updatedCR = cmdb.setCrClosedAndImplemented(crID);
            CRArray newcr = cmdb.getCRByID(updatedCR);
            return new listOfCRs(15, newcr);
        }


        #endregion

        //=================================CIM==================================
        #region CIM


        [WebMethod]
        public listOfCRs getSheduledNotImplementedCRs(APIAccessToken token) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isChangeImplementer(token.username))
                return new listOfCRs(16);
            long cimID = cmdb.getUserIdByUsername(token.username);
            CRArray they = cmdb.getApprovedNotImplementerCRsByCIM(cimID);
            return new listOfCRs(15, they);
        }

        public listOfCRs markCRasImplemented(APIAccessToken token, long crid) {
            if (!Security.IsSenderValid(token))
                return new listOfCRs(14);
            if (!Security.isChangeImplementer(token.username))
                return new listOfCRs(16);
            long upd = cmdb.setCrClosedAndNotImplemented(crid);
            CRArray result = cmdb.getCRByID(upd);
            return new listOfCRs(15, result);
        }
        
        #endregion

        /* DEBUG METHODS 
        [WebMethod]
        public AuthentificatedUser ShowSettings()
        {   
            return authentificatedUsers[0];
        }

        [WebMethod]
        public exa example()
        {
            return ex;
        }
        */
        
    }
}
